use bevy::prelude::*;
use crate::{CurrentFloor, ReqQueue};
use crate::components::{ButtonRequest, MainCamera};
use crate::components::RequestType;
use crate::movement::ButtonState;
use crate::movement::PIXEL_PER_FLOOR;

pub struct UiPlugin;

impl Plugin for UiPlugin {
    fn build(&self, app: &mut App) {
        app
            .add_startup_system(setup)
            .add_system(floor_button_system)
            .add_system(updown_button_system)
            .add_system(update_ui_floor);
    }
}


const NORMAL_BUTTON: Color = Color::rgb(0.15, 0.15, 0.15);
const HOVERED_BUTTON: Color = Color::rgb(0.25, 0.25, 0.25);
const PRESSED_BUTTON: Color = Color::rgb(0.35, 0.75, 0.35);

use super::ELEVATOR_TOP_FLOOR;
use super::WINDOW_HEIGHT;

#[derive(Component)]
pub struct ResourceText;

fn update_ui_floor(
    mut query: Query<&mut Text, With<ResourceText>>,
    floor: Res<CurrentFloor>,
) {
    for mut text in query.iter_mut() {
        text.sections[0].value = format!("{}", floor.0);
    }
}

#[derive(Bundle)]
struct UpdownButtonBundle {
    updown_button: UpdownButton,
    #[bundle]
    button_bundle: ButtonBundle,
}

#[derive(Component)]
struct UpdownButton {
    button_type: RequestType,
    at: i32,
    lighted: bool,
}

#[derive(Bundle)]
struct FloorButtonBundle {
    floor_button: FloorButton,
    #[bundle]
    button_bundle: ButtonBundle,
}

#[derive(Component)]
struct FloorButton {
    at: i32,
    lighted: bool,
}

// 将button_state同步到每个按钮的点亮与否的状态
fn button_state_changed_sync_system(
    mut updown_button_query: Query<&mut UpdownButton>,
    mut floor_query: Query<&mut FloorButton>,
    button_state: Res<ButtonState>,
) {
    if button_state.is_changed() {
        for mut updown_button in updown_button_query.iter_mut() {
            if updown_button.button_type == RequestType::UP {
                updown_button.lighted = button_state.up_button[updown_button.at as usize - 1];
            } else {
                updown_button.lighted = button_state.down_button[updown_button.at as usize - 1];
            }
        }
        for mut floor_button in floor_query.iter_mut() {
            floor_button.lighted = button_state.floor_button[floor_button.at as usize - 1];
        }
    }
}

fn updown_button_system(
    mut query: Query<
        (&Interaction, &mut UpdownButton, &mut UiColor),
        (Or<(Changed<Interaction>, Changed<UpdownButton>)>, With<UpdownButton>), // use or to detect the finished button
    >,
    mut request_query: Query<&mut ReqQueue>,
    mut button_state: ResMut<ButtonState>,
) {
    let mut request = request_query.single_mut();
    for (interaction, mut updown_button, mut color) in query.iter_mut() {
        match *interaction {
            Interaction::Clicked => {
                updown_button.lighted = !updown_button.lighted;
                // update the button state
                if updown_button.button_type == RequestType::UP {
                    button_state.up_button[updown_button.at as usize - 1] = updown_button.lighted
                } else {
                    button_state.down_button[updown_button.at as usize - 1] = updown_button.lighted
                }
                if updown_button.lighted {
                    *color = PRESSED_BUTTON.into();
                } else {
                    *color = NORMAL_BUTTON.into();
                }
                if updown_button.lighted {
                    request.request_queue.push_back(ButtonRequest{req_type: updown_button.button_type, at: updown_button.at});
                } else {
                    // todo: remove the request in the queue
                    let length = request.request_queue.len();
                    for _i in 0..length {
                        let ele = request.request_queue.pop_front().unwrap();
                        if ele.at != updown_button.at || ele.req_type != updown_button.button_type {
                            request.request_queue.push_back(ele);
                        }
                    }
                }
                // println!("{:?}", request.request_queue);
            },
            Interaction::Hovered => {
                if !updown_button.lighted {
                    *color = HOVERED_BUTTON.into();
                }
            },
            Interaction::None => {
                // text.sections[0].value = "Button".to_string();
                if !updown_button.lighted {
                    *color = NORMAL_BUTTON.into();
                }
            },
        }
    }
}

fn floor_button_system(
    mut interaction_query: Query<
        (&Interaction, &mut FloorButton, &mut UiColor),
        (Or<(Changed<Interaction>, Changed<FloorButton>)>, With<FloorButton>),
    >,
    mut request_query: Query<&mut ReqQueue>,
    mut button_state: ResMut<ButtonState>,
) {
    let mut request = request_query.single_mut();
    for (interaction, mut floor_button, mut color) in interaction_query.iter_mut() {
        // let mut text = text_query.get_mut(children[0]).unwrap();
        match *interaction {
            Interaction::Clicked => {
                floor_button.lighted = !floor_button.lighted;

                button_state.floor_button[floor_button.at as usize - 1] = floor_button.lighted;
                if floor_button.lighted {
                    request.request_queue.push_back(ButtonRequest{req_type: RequestType::FLOOR, at: floor_button.at });
                } else {
                    // 取消请求
                    let length = request.request_queue.len();
                    for _i in 0..length {
                        let ele = request.request_queue.pop_front().unwrap();
                        if ele.req_type != RequestType::FLOOR || ele.at != floor_button.at {
                            request.request_queue.push_back(ele);
                        }
                    }
                }

                if floor_button.lighted {
                    *color = PRESSED_BUTTON.into();
                } else {
                    *color = NORMAL_BUTTON.into();
                }
            },
            Interaction::Hovered => {
                if !floor_button.lighted {
                    *color = HOVERED_BUTTON.into();
                }
            },
            Interaction::None => {
                // text.sections[0].value = "Button".to_string();
                if !floor_button.lighted {
                    *color = NORMAL_BUTTON.into();
                }
            },
        }
    }
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    // ui camera
    let font = asset_server.load("fonts/FiraSans-Bold.ttf");
    commands.spawn_bundle(OrthographicCameraBundle::new_2d())
        .insert(MainCamera);
    commands.spawn_bundle(UiCameraBundle::default());

    commands.spawn_bundle(screen_fill_node())
        .with_children(|parent|{
            parent
                .spawn_bundle(left_border())
                .with_children(|parent| {
                    // left vertical fill (content)
                    parent
                        .spawn_bundle(left_fill())
                        .with_children(|parent| {
                            // updown button
                            for i in 0..ELEVATOR_TOP_FLOOR {
                                parent.spawn_bundle(group_button())
                                    .with_children(|parent| {
                                        if i != ELEVATOR_TOP_FLOOR-1 {
                                            parent.spawn_bundle(updown_button(RequestType::UP, i as i32 +1))
                                                .with_children(|parent| {
                                                    parent.spawn_bundle(floor_text("⬆", font.clone()));
                                                });
                                        }
                                        if i != 0 {
                                            parent.spawn_bundle(updown_button(RequestType::DOWN, i as i32 +1))
                                                .with_children(|parent| {
                                                    parent.spawn_bundle(floor_text("⬇", font.clone()));
                                                });
                                        }
                                    });
                            }
                        });
                });
            // right vertical fill
            parent
                .spawn_bundle(right_fill())
                .with_children(|parent| {
                    for i in 0..ELEVATOR_TOP_FLOOR {
                        parent.spawn_bundle(floor_button(i as i32 +1))
                            .with_children(|parent|{
                                parent.spawn_bundle(floor_text(&(i+1).to_string(), font.clone()));
                            });
                    }
                    // Floor Text
                    parent.spawn_bundle(resource_text(font.clone()))
                        .insert(ResourceText);
                });
            // Absolute position
            for i in 0..ELEVATOR_TOP_FLOOR {
                parent.spawn_bundle(floor_line(i as i32 +1));
            }
        });
}


fn floor_text(name: &str, font: Handle<Font>) -> TextBundle {
    TextBundle {
        text: Text::with_section(
            name,
            TextStyle {
                font,
                font_size: 40.0,
                color: Color::rgb(0.9, 0.9, 0.9),
            },
            Default::default(),
        ),
        ..Default::default()
    }
}

fn screen_fill_node() -> NodeBundle {
    NodeBundle {
        style: Style {
            size: Size::new(Val::Percent(100.0), Val::Percent(100.0)),
            justify_content: JustifyContent::SpaceBetween,
            // flex_direction: FlexDirection::Column,
            ..Default::default()
        },
        color: Color::NONE.into(),
        ..Default::default()
    }
}

fn right_fill() -> NodeBundle {
    NodeBundle {
        style: Style {
            size: Size::new(Val::Px(200.0), Val::Percent(100.0)),
            flex_direction: FlexDirection::Column,
            justify_content: JustifyContent::Center,
            // size: Size::new(Val::Px(200.0), Val::Percent(100.0)),
            ..Default::default()
        },
        color: Color::rgb(0.15, 0.15, 0.15).into(),
        ..Default::default()
    }
}

fn left_fill() -> NodeBundle {
    NodeBundle {
        style: Style {
            size: Size::new(Val::Px(200.0), Val::Percent(100.0)),
            border: Rect::all(Val::Px(5.0)),
            flex_direction: FlexDirection::Column,
            // justify_content: JustifyContent::Center,
            ..Default::default()
        },
        color: Color::rgb(0.15, 0.15, 0.15).into(),
        ..Default::default()
    }
}

fn left_border() -> NodeBundle {
    NodeBundle {
        style: Style {
            size: Size::new(Val::Px(200.0), Val::Percent(100.0)),
            border: Rect::all(Val::Px(5.0)),
            ..Default::default()
        },
        color: Color::rgb(0.65, 0.65, 0.65).into(),
        ..Default::default()
    }
}

fn updown_button(button_type: RequestType, at: i32) -> UpdownButtonBundle {
    UpdownButtonBundle {
        updown_button: UpdownButton {
            button_type,
            at,
            lighted: false,
        },
        button_bundle: push_button_bundle(),
    }
}

fn floor_button(at: i32) -> FloorButtonBundle {
    FloorButtonBundle {
        floor_button: FloorButton {
            at,
            lighted: false,
        },
        button_bundle: push_button_bundle(),
    }
}

fn floor_line(floor: i32) -> NodeBundle {
    NodeBundle {
        style: Style {
            size: Size::new(Val::Px(200.0), Val::Px(5.0)),
            position_type: PositionType::Absolute,
            position: Rect{
                bottom: Val::Px(floor as f32 * PIXEL_PER_FLOOR as f32),
                left: Val::Percent(35.0),
                ..default()},
            ..Default::default()
        },
        color: Color::BLACK.into(),
        ..Default::default()
    }
}

fn push_button_bundle() -> ButtonBundle {
    ButtonBundle {
        style: Style {
            size: Size::new(Val::Px(WINDOW_HEIGHT / 10.), Val::Px(WINDOW_HEIGHT / 10.)),
            // center button
            margin: Rect::all(Val::Auto),
            // horizontally center child text
            justify_content: JustifyContent::Center,
            // vertically center child text
            align_items: AlignItems::Center,
            ..Default::default()
        },
        color: NORMAL_BUTTON.into(),
        ..Default::default()
    }
}

fn group_button() -> NodeBundle {
    NodeBundle {
        style: Style {
            size: Size::new(Val::Percent(100.0), Val::Percent(100.0 / 6.0)),
            justify_content: JustifyContent::SpaceBetween,
            flex_direction: FlexDirection::Row,
            ..Default::default()
        },
        color: Color::NONE.into(),
        ..Default::default()
    }
}

fn resource_text(font: Handle<Font>) -> TextBundle {
    TextBundle {
        style: Style {
            align_self: AlignSelf::FlexStart,
            position: Rect {
                top: Val::Px(0.0),
                left: Val::Px(50.0),
                ..Default::default()
            },
            ..Default::default()
        },
        text: Text::with_section(
            "1",
            TextStyle {
                font,
                font_size: 35.0,
                color: Color::GREEN,
            },
            Default::default(),
        ),
        ..Default::default()
    }
}